Fix ODB: DEF_file in 3dbx (Issue #10077)#10096
Conversation
|
clang-tidy review says "All clean, LGTM! 👍" |
There was a problem hiding this comment.
Code Review
This pull request introduces logic to read DEF files for chiplets and chip instances, using a boolean property to track whether the file has already been processed. The review highlights a potential for redundant DEF reads in createChiplet due to a missing check, suggests refactoring the duplicated DEF reading logic into a shared helper function, and recommends using std::vector::assign for more efficient population of the search_libs vector.
| chiplet.external.def_file.c_str(), | ||
| chip, | ||
| /*issue_callback*/ false); | ||
| odb::dbBoolProperty::create(chip, "def_file_read", true); |
There was a problem hiding this comment.
While setting the def_file_read property here is correct, the corresponding check to see if it's already set (similar to the one added in createChipInst at line 683) is missing at the beginning of the DEF reading block in this function (around line 456). This could lead to redundant DEF reads if createChiplet is called multiple times for the same master chip.
| if (!chip_inst.external.def_file.empty()) { | ||
| if (odb::dbProperty::find(chip, "def_file_read") == nullptr) { | ||
| if (chip->getBlock() != nullptr) { | ||
| odb::dbBlock::destroy(chip->getBlock()); | ||
| } | ||
| odb::defin def_reader(db_, logger_, odb::defin::DEFAULT); | ||
| std::vector<odb::dbLib*> search_libs; | ||
| for (odb::dbLib* lib : db_->getLibs()) { | ||
| search_libs.push_back(lib); | ||
| } | ||
| def_reader.readChip( | ||
| search_libs, chip_inst.external.def_file.c_str(), chip, false); | ||
| odb::dbBoolProperty::create(chip, "def_file_read", true); | ||
| } | ||
| } |
There was a problem hiding this comment.
The logic for reading a DEF file for a chiplet is duplicated between createChiplet and createChipInst. This logic (checking for the property, destroying the existing block, populating search libraries, and reading the chip) should be refactored into a shared free function within a namespace to improve maintainability and ensure consistency.
References
- Helper logic should be defined as a free function in a namespace rather than as a local lambda within a function.
| std::vector<odb::dbLib*> search_libs; | ||
| for (odb::dbLib* lib : db_->getLibs()) { | ||
| search_libs.push_back(lib); | ||
| } |
There was a problem hiding this comment.
The population of the search_libs vector can be simplified using std::vector::assign. This is more efficient and follows the general rule for copying elements from a dbSet to a std::vector.
std::vector<odb::dbLib*> search_libs;
search_libs.assign(db_->getLibs().begin(), db_->getLibs().end());References
- To copy elements from a dbSet to a std::vector, use the vector::assign() method with iterators from the dbSet, as direct assignment is not supported.
|
clang-tidy review says "All clean, LGTM! 👍" |
osamahammad21
left a comment
There was a problem hiding this comment.
Remove writing a def file in the 3dbv for each chiplet and add a test case.
|
|
||
| if (!chip_inst.external.def_file.empty()) { | ||
| if (chip->getBlock() != nullptr) { | ||
| odb::dbBlock::destroy(chip->getBlock()); |
There was a problem hiding this comment.
you probably should log an error here. There can't be 2 instances of the same chiplet with a def file each.
| odb::defin def_reader(db_, logger_, odb::defin::DEFAULT); | ||
| std::vector<odb::dbLib*> search_libs; | ||
| for (odb::dbLib* lib : db_->getLibs()) { | ||
| search_libs.push_back(lib); | ||
| } | ||
| def_reader.readChip( | ||
| search_libs, chip_inst.external.def_file.c_str(), chip, false); |
There was a problem hiding this comment.
This is the same code written in createChiplet, wrap in an inline function to reduce code duplication.
| odb::dbBoolProperty::create(chip, "def_file_read", true); | ||
| if (auto* prop = odb::dbStringProperty::find(chip, "def_file_path")) { | ||
| prop->setValue(chiplet.external.def_file.c_str()); | ||
| } else { | ||
| odb::dbStringProperty::create( | ||
| chip, "def_file_path", chiplet.external.def_file.c_str()); | ||
| } |
There was a problem hiding this comment.
why? I don't think these properties are needed.
| odb::dbBoolProperty::create(chip, "def_file_read", true); | ||
| if (auto* prop = odb::dbStringProperty::find(chip, "def_file_path")) { | ||
| prop->setValue(chip_inst.external.def_file.c_str()); | ||
| } else { | ||
| odb::dbStringProperty::create( | ||
| chip, "def_file_path", chip_inst.external.def_file.c_str()); | ||
| } |
| auto* chip = inst->getMasterChip(); | ||
| if (odb::dbProperty::find(chip, "def_file_read") != nullptr) { | ||
| YAML::Node external_node = instance_node["external"]; | ||
| external_node["def_file"] = std::string(chip->getName()) + ".def"; | ||
| } |
There was a problem hiding this comment.
This is going to end up in all instances of that chiplet having a def file defined. This is incorrect. There should only be one chipInst with a defined def_file. It doesn't matter which one, but it should be only one.
|
clang-tidy review says "All clean, LGTM! 👍" |
|
All requested changes have been made. |
osamahammad21
left a comment
There was a problem hiding this comment.
The current implementation creates a block for every chiplet definition created. This is necessary for reading the bump map and populating the block with the bumps. We need, somehow, to delay reading the bump map to after we've read the defs of the master chiplet instances. It is gonna look ugly, but that's unavoidable with the current standard.
|
clang-tidy review says "All clean, LGTM! 👍" |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 21 days if no further activity occurs. Remove the |
osamahammad21
left a comment
There was a problem hiding this comment.
I'm not a fan of the call_depth_ approach. I understand the underlying reason for it: the bump map can only be created once the chiplet's block exists, so we need to guarantee the chiplet DEF is read before the bmap. The depth counter is how we currently force "all DEFs are in" before flushing the deferred bumps.
But this only holds when everything is reachable from a single top-level read (e.g. a read_3dbx that includes the .3dbv). What happens with a standalone read_3dbv followed by a separate read_3dbx? At the end of read_3dbv the depth is already back to 0, so the bumps get flushed, but the inst-level DEF doesn't arrive until the later read_3dbx command. The ordering guarantee breaks across separate commands, and no end-of-read flush can fix that.
I'd suggest a different direction: instead of deferring the bumps, create the block + bumps eagerly at .3dbv time and introduce a new defin mode dedicated to 3DBlox for the DEF read. It would:
- operate on a block that already exists (created when the chiplet definition was read), rather than creating one from scratch and erroring if one is present;
- handle duplicate data correctly: a bump can appear in both the bmap and the DEF, along with its associated bterm and net, so the DEF checks instead of duplicating or erroring.
This makes the DEF read order-independent and drops call_depth_ / pending_bmaps_ entirely.
Separately, we still need to track which chips have already had a DEF read and error out when 2+ instances each define a DEF for the same chiplet.
f15bf78 to
81b65a2
Compare
81b65a2 to
99ead73
Compare
…0077) Per the 3DBlox standard (sec 4.3.1) the DEF file is associated with a ChipletInst (in the .3dbx) rather than the ChipletDef. Read it from either location (whichever exists) onto the master chiplet block. - Add defin::THREE_D_BLOX mode: reads a DEF onto an already-existing block, find-or-creating COMPONENTS/PINS/NETS and deduplicating data shared with the bump map (a bump may appear in both the bmap and the DEF) instead of erroring or duplicating. defin::readChip now reports success so the chiplet's DEF is marked read only on success. - 3dblox: create block+bumps eagerly at .3dbv time; read each chiplet's DEF once (chips_with_def_); error (ODB-547) when two instances of the same chiplet each carry a DEF. - Writers: emit def_file on a single ChipletInst in the .3dbx (no longer in the .3dbv), chosen deterministically by name; sort the 3dbv LEF_file output. - external spec: single-valued external fields (def_file/verilog_file/sdc_file) accept a scalar or a single-element list via BaseParser::extractSinglePathFromList and error (ODB-521) on more than one entry. Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
99ead73 to
a166700
Compare
fix issue #10077